package org.example.springbootproject.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.example.springbootproject.config.JwtUtil;
import org.example.springbootproject.config.KaptchaUtil;
import org.example.springbootproject.dto.PaperDetailDTO;
import org.example.springbootproject.entity.*;
import org.example.springbootproject.mapper.*;
import org.example.springbootproject.service.ExamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class ExamServiceImpl implements ExamService {

    @Autowired
    private ExamPaperMapper examPaperMapper;

    @Autowired
    private QuestionBankMapper questionBankMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private PaperQuestionMapper paperQuestionMapper;

    @Autowired
    private ExamRuleMapper examRuleMapper;

    @Autowired
    private ExamRuleSubMapper examRuleSubMapper;

    @Autowired
    private UserMapper userMapper;

    private final KaptchaUtil  kaptchaUtil;
    private final JwtUtil jwtUtil;
    @Autowired
    public ExamServiceImpl(JwtUtil jwtUtil,  KaptchaUtil kaptchaUtil) {
        this.jwtUtil = jwtUtil;
        this.kaptchaUtil = kaptchaUtil;
    }

    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ExamServiceImpl.class);

    // ================== 试卷相关 ==================
    @Override
    public List<ExamPaper> getAllPapers() {
        return examPaperMapper.selectList(null);
    }
    @Override
    public ExamPaper getPaperById(Long paperId) {
        return examPaperMapper.selectById(paperId);
    }
    @Override
    @Transactional
    public void createPaper(ExamPaper examPaper) {
        // 1. 插入试卷基本信息（包含 ruleId）
        examPaperMapper.insert(examPaper);
        Long ruleId = examPaper.getRuleId();
        if (ruleId == null) {
            throw new IllegalArgumentException("出题规则 ID 不能为空");
        }
        // 2. 查询出题规则及其子规则
        ExamRule examRule = examRuleMapper.selectById(ruleId);
        if (examRule == null) {
            throw new IllegalArgumentException("出题规则不存在");
        }
        List<SubRule> subRules = examRuleSubMapper.selectList(
                new QueryWrapper<SubRule>().eq("rule_id", ruleId));
        // 3. 抽取题目并构建 PaperQuestion 列表
        List<PaperQuestion> paperQuestions = new ArrayList<>();
        int totalScore = 0;
        for (SubRule sub : subRules) {
            List<Question> questions = questionMapper.selectList(null).stream()
                    .filter(q -> q.getType().equals(sub.getQuestionType()))
                    .filter(q -> q.getBankId().equals(sub.getBankId()))
                    .limit(sub.getNum())
                    .toList();
            for (Question q : questions) {
                PaperQuestion pq = new PaperQuestion();
                pq.setPaperId(examPaper.getId());
                pq.setQuestionId(q.getId());
                pq.setScore(sub.getPerScore());
                paperQuestions.add(pq);
                totalScore += sub.getPerScore();
            }
        }
        // 4. 更新试卷总分和及格分
        examPaper.setId(examPaper.getId()); // 确保 ID 已经存在（插入后 MyBatis Plus 会自动填充）
        examPaper.setTotalScore(totalScore);
        examPaper.setPassScore((int) Math.ceil(totalScore * 0.6));
        examPaperMapper.updateById(examPaper);
        // 5. 批量插入 paper_question 表
        if (!paperQuestions.isEmpty()) {
            paperQuestionMapper.insertBatch(paperQuestions); // 自定义批量插入方法
        }
    }
    @Override
    public void updatePaper(ExamPaper examPaper) {
        examPaperMapper.updateById(examPaper);
    }
    @Override
    public void deletePaper(Long id) {
        // 1. 先删除 paper_question 表中关联记录
        paperQuestionMapper.delete(new QueryWrapper<PaperQuestion>().eq("paper_id", id));
        // 2. 再删除 exam_paper 表中的试卷
        examPaperMapper.deleteById(id);
    }
    @Override
    public PaperDetailDTO getPaperDetailsWithQuestions(Long paperId) {
        ExamPaper examPaper = examPaperMapper.selectById(paperId);
        if (examPaper == null) {
            throw new IllegalArgumentException("试卷不存在");
        }
        List<PaperQuestion> pqList = paperQuestionMapper.selectList(
                new QueryWrapper<PaperQuestion>().eq("paper_id", paperId));
        List<PaperDetailDTO.QuestionInfo> questionInfos = pqList.stream()
                .map(pq -> {
                    Question question = questionMapper.selectById(pq.getQuestionId());
                    if (question == null) return null;
                    return new PaperDetailDTO.QuestionInfo(pq, question);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        return new PaperDetailDTO(examPaper, questionInfos);
    }

    // ================== 出题规则相关 ==================
    @Override
    public List<ExamRule> getAllExamRules() {
        List<ExamRule> rules = examRuleMapper.selectList(null);

        for (ExamRule rule : rules) {
            List<SubRule> subRules = examRuleSubMapper.selectList(
                    new QueryWrapper<SubRule>().eq("rule_id", rule.getId()));
            rule.setSubRules(subRules);
        }

        return rules;
    }

    @Override
    public void createExamRule(ExamRule examRule) {
        // 先插入主规则
        examRule.setCreateTime(LocalDateTime.now());
        examRuleMapper.insert(examRule); // 此时会生成自增ID（假设你用的是自增）

        // 再插入子规则
        if (examRule.getSubRules() != null && !examRule.getSubRules().isEmpty()) {
            for (SubRule sub : examRule.getSubRules()) {
                sub.setRuleId(examRule.getId()); // 此时 examRule.getId() 已经有值
                examRuleSubMapper.insert(sub);
            }
        }
    }

    @Override
    public ExamRule getExamRuleById(Long id) {
        return examRuleMapper.selectById(id);
    }
    @Override
    public void updateExamRule(ExamRule examRule) {
        // 更新主规则
        examRuleMapper.updateById(examRule);
        // 删除原有子规则
        examRuleSubMapper.delete(new QueryWrapper<SubRule>().eq("rule_id", examRule.getId()));
        // 插入新的子规则
        for (SubRule sub : examRule.getSubRules()) {
            sub.setRuleId(examRule.getId());
            examRuleSubMapper.insert(sub);
        }
    }

    @Override
    public void deleteExamRule(Long id) {
        examRuleSubMapper.delete(new QueryWrapper<SubRule>().eq("rule_id", id));
        examRuleMapper.deleteById(id);
    }


    // ================== 题库相关 ==================
    @Override
    public List<QuestionBank> getAllBanks() {
        return questionBankMapper.selectList(null);
    }
    @Override
    public QuestionBank getBankById(Long bankId) {
        return questionBankMapper.selectById(bankId);
    }
    @Override
    public void addBank(QuestionBank bank) {
        questionBankMapper.insert(bank);
        // 初始化题目数量
        questionBankMapper.updateQuestionCountById(bank.getId());
    }
    @Override
    public void deleteBank(Long id) {
        questionBankMapper.deleteById(id);
    }
    @Override
    public void updateBank(QuestionBank bank) {
        questionBankMapper.updateById(bank);
    }
    @Override
    public List<QuestionBank> searchBanks(Map<String, String> criteria) {
        String keyword = criteria.getOrDefault("keyword", "").toLowerCase();
        return getAllBanks().stream()
                .filter(b -> b.getName().toLowerCase().contains(keyword) ||
                        b.getDescription().toLowerCase().contains(keyword))
                .collect(Collectors.toList());
    }

    // ================== 题目相关 ==================
    @Override
    public void updateQuestionCount(Long bankId) {
        questionBankMapper.updateQuestionCountById(bankId);
    }

    @Override
    public List<Question> getAllQuestions() {
        return questionMapper.selectList(null);
    }
    @Override
    public List<Question> getQuestionsByBankAndType(Long bankId, String type) {
        return questionMapper.selectList(null).stream()
                .filter(q -> (bankId == null || q.getBankId().equals(bankId)) &&
                        (type == null || q.getType().equals(type)))
                .collect(Collectors.toList());
    }


    @Override
    public void addQuestion(Question question) {
        questionMapper.insert(question);
        // 更新题库题目数量
        updateQuestionCount(question.getBankId());
    }

    @Override
    public void deleteQuestion(Long id) {
        Question question = questionMapper.selectById(id);
        if (question != null) {
            Long bankId = question.getBankId();
            questionMapper.deleteById(id);
            // 更新题库题目数量
            updateQuestionCount(bankId);
        }
    }

    @Override
    public void updateQuestion(Question question) {
        Question oldQuestion = questionMapper.selectById(question.getId());
        if (oldQuestion != null) {
            Long oldBankId = oldQuestion.getBankId();
            questionMapper.updateById(question);
            // 如果题目所属题库发生变化，更新新旧题库的题目数量
            if (!oldBankId.equals(question.getBankId())) {
                updateQuestionCount(oldBankId);
                updateQuestionCount(question.getBankId());
            } else {
                // 否则只更新当前题库的题目数量
                updateQuestionCount(question.getBankId());
            }
        }
    }

    @Override
    public List<Question> searchQuestions(Map<String, String> criteria) {
        long bankId = Long.parseLong(criteria.getOrDefault("bankId", "0"));
        String type = criteria.getOrDefault("type", "");
        String keyword = criteria.getOrDefault("keyword", "").toLowerCase();

        return questionMapper.selectList(null).stream()
                .filter(q -> (bankId == 0 || q.getBankId().equals(bankId)) &&
                        (type.isEmpty() || q.getType().equals(type)) &&
                        (q.getContent().toLowerCase().contains(keyword)))
                .collect(Collectors.toList());
    }

    // ================== 用户管理 ==================
    @Override
    public void updateUser(Long id, User user) {
        user.setId(id);
        if (user.getPassword() != null && !user.getPassword().isEmpty()) {
            user.setPassword(md5(user.getPassword()));
        }
        userMapper.updateById(user);
    }

    @Override
    public void deleteUser(Long id) {
        userMapper.deleteById(id);
    }

    @Override
    public User getCurrentUser(String token) {
        String username = jwtUtil.extractUsername(token);
        return userMapper.selectByUsername(username);
    }
    @Override
    public List<User> getAllUsers() {
        return userMapper.selectList(null);
    }

    @Override
    public Map<String, Object> login(String username, String password, String captcha, String imgToken, String ip) {
        logger.info("用户输入的验证码: {}", captcha);
        // 验证验证码
        if (captcha == null || !kaptchaUtil.validateCaptcha(imgToken, captcha)) {
            throw new RuntimeException("验证码错误");
        }
        User user = userMapper.selectByUsername(username);
        if (user == null || !user.getPassword().equals(md5(password))) {
            throw new RuntimeException("用户名或密码错误");
        }
        // 更新最近登录时间和 IP
        LocalDateTime now = LocalDateTime.now();
        userMapper.updateLastLogin(user.getId(), now, ip);
        String token = jwtUtil.generateToken(user.getUsername(), user.getRole());
        return Map.of(
                "token", token,
                "role", user.getRole(),
                "username", user.getUsername()
        );
    }

    @Override
    public void register(String username, String password, String ip) {
        if (userMapper.selectByUsername(username) != null) {
            throw new RuntimeException("用户名已存在");
        }

        User newUser = new User();
        newUser.setUsername(username);
        newUser.setPassword(md5(password)); // 密码加密
        newUser.setRole("user"); // 默认角色为 user
        newUser.setLastLoginIp(ip);
        newUser.setLastLoginTime(LocalDateTime.now());

        userMapper.insert(newUser);
    }

    private String md5(String input) {
        return DigestUtils.md5DigestAsHex(input.getBytes());
    }
}